import { defineStore, acceptHMRUpdate } from 'pinia'
import { ethers, Contract, utils } from "ethers";
import { ElNotification } from 'element-plus'

let PROVIDER = null
export const useEthersStore = defineStore({
  id: 'ethers',
  state: () => {
    return {
      defaultChainId: 4,
      gameContract: '0x271257220369B356BCd3A5804C9463164B311507',
      account: null,
    }
  },
  getters: {
    address (state) {
      if (!state.account) return ''
      return state.account.replace(/^(.{6})(?:\w+)(.{6})$/, '$1********$2')
    }
  },
  actions: {
    // connect: 是否主动连接
    async connect (connect) {
      try {
        const { ethereum } = window;
        if (!ethereum) {
          // 验证是否安装 Metamask
          ElNotification.warning({
            title: 'Warning',
            message: 'Metamask not installed!',
          })
          return;
        }
        PROVIDER = new ethers.providers.Web3Provider(ethereum);
        if (!(await this.checkIfConnected(connect)) && connect) {
          await this.requestAccess()
        }

        ethereum.on('networkChanged', () => {
          this.checkNetwork()
        })
        ethereum.on('accountsChanged', (address) => {
          this.account = address[0]
        })
        ethereum.on('message', message => {
          console.log('ethereum message', message)
        })
        ethereum.on('disconnect', () => {
          this.disconnect()
        })
      } catch (error) {
        console.log(error);
      }
    },
    async checkIfConnected (connect) {
      const { ethereum } = window;
      const isUnlocked = await ethereum._metamask.isUnlocked()
      if (!isUnlocked && !connect) {
        return false
      }
      const accounts = await ethereum.request({ method: "eth_accounts" });
      if (accounts.length !== 0) {
        localStorage.setItem('connect_type', 'mateMask')
        this.$patch({
          account: accounts[0]
        })
        await this.checkNetwork()
        return true;
      } else {
        return false;
      }
    },
    async requestAccess () {
      try {
        const { ethereum } = window;
        const accounts = await ethereum.request({
          method: "eth_requestAccounts",
        });
        this.account = accounts[0]
        await this.checkNetwork()
      } catch (error) {
        console.log('[ error ] >', error)
      }
    },
    async checkNetwork () {
      const { chainId } = await PROVIDER.getNetwork()
      try {
        if (this.defaultChainId !== chainId) {
          if (await this.switchNetwork()) {
            await this.addNetwork()
          }
        }
      } catch (error) {
        console.log('[ error ] >', error)
      }
    },
    async addNetwork () {
      console.log('[ addNetwork ] >')
    },
    async switchNetwork () {
      try {
        await ethereum.request({
          method: "wallet_switchEthereumChain",
          params: [{ chainId: utils.hexValue(this.defaultChainId) }],
        });
        return true;
      } catch (switchError) {
        return false;
      }
    },
    // 合约实例
    instanceContract () {
      try {
        const abi = [
          'function mintItem(address player, string tokenURI, uint256 score, uint256 step, uint256 startTime, uint256 endTime) returns (uint256)',
          'function tokenURI(uint256 tokenId) view returns (string)'
        ]
        const signer = PROVIDER.getSigner();
        const connectedContract = new Contract(
          this.gameContract,
          abi,
          signer
        );
        return connectedContract;
      } catch (error) {
        console.log('[ error ] >', error)
        return null
      }
    },
    disconnect () {
      localStorage.removeItem('connect_type')
      this.account = null
    }
  },
})


if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(useEthersStore, import.meta.hot))
}
